package middleware

import (
	"gitee.com/buddyxiao/ginblog/utils"
	"gitee.com/buddyxiao/ginblog/utils/errmsg"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
	"time"
)

var JwtKey = []byte(utils.JwtKey)

type MyClaim struct {
	Username string `json:"username"`
	jwt.StandardClaims
}

// SetToken 生成token
func SetToken(username string) (string, int) {
	expireTime := time.Now().Add(10*time.Hour)
	setClaims := MyClaim{
		Username: username,
		StandardClaims:jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(),
			Issuer: "ginblog",
		},
	}
	reqClaim := jwt.NewWithClaims(jwt.SigningMethodHS256,setClaims)
	token , err := reqClaim.SignedString(JwtKey)
	if err != nil {
		return "",errmsg.ERROR
	}
	return token,errmsg.SUCCESS

}

// CheckToken 验证token
func CheckToken(token string) (*MyClaim,int){
	sToken , _ :=jwt.ParseWithClaims(token,&MyClaim{}, func(token *jwt.Token) (interface{}, error) {
		return JwtKey,nil
	})
	if key,ok :=sToken.Claims.(*MyClaim);ok && sToken.Valid {
		return key,errmsg.SUCCESS
	}else{
		return nil,errmsg.ERROR
	}
}

// JwtToken jwt中间件
func JwtToken() gin.HandlerFunc {
	return func(context *gin.Context) {
		tokenHeader := context.Request.Header.Get("Authorization")
		// 前端没传递token
		code := errmsg.SUCCESS
		if tokenHeader == "" {
			code = errmsg.ERROR_TOKEN_NOT_EXIST
			context.JSON(http.StatusOK,gin.H{
				"code": code,
				"msg": errmsg.GetErrMsg(code),
			})
			context.Abort()
			return
		}
		// 传递的token格式有问题
		checkToken := strings.SplitN(tokenHeader," ",2)
		if len(checkToken) != 2 && checkToken[0] != "Bearer" {
			code = errmsg.ERROR_TOKEN_TYPE_WRONG
			context.JSON(http.StatusOK,gin.H{
				"code": code,
				"msg": errmsg.GetErrMsg(code),
			})
			context.Abort()
			return
		}
		// token内容有问题
		key,cCode := CheckToken(checkToken[1])
		if cCode == errmsg.ERROR {
			code = errmsg.ERROR_TOKEN_WRONG
			context.JSON(http.StatusOK,gin.H{
				"code": code,
				"msg": errmsg.GetErrMsg(code),
			})
			context.Abort()
			return
		}
		// token过期了
		if time.Now().Unix() > key.ExpiresAt {
			code = errmsg.ERROR_TOKEN_TIMEOUT
			context.JSON(http.StatusOK,gin.H{
				"code": code,
				"msg": errmsg.GetErrMsg(code),
			})
			context.Abort()
			return
		}
		context.Set("username",key.Username)
		context.Next()
	}
}